package com.activity;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONException;

import tShareLife.facebook.FacebookError;
import tShareLife.facebook.Util;
import ShareLife.gar.FbMgr;
import ShareLife.gar.ToolOld;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentUris;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.Toast;

import com.misc.Tool;
import com.type.Friend;
import com.type.LocalContacts;
import com.type.User;
import com.type.newTypeUser;
import com.type.photoByteArray;
import com.view.AppView;

public class MainActivity extends Activity {
	// constant
	public static final String SERVER_IP = "10.4.81.21";
//	public static final String SERVER_IP = "192.168.1.100";
	public static final String MY_PHONE_NUMBER = "my_phone_number";
	public static final String FRIEND_PHONE_NUMBER = "friend_phone_number";
	
	static final String LOGIN_PHONE_NUMBER = "login_phone_number";
	static final String LOGIN_COMPLETE_ACTION = "login_complete_action";
	static final String FRIEND_LIST = "com.activity.friend_list";
	static final String SELECTED_FRIEND = "com.activity.selected_friend";
	static final String FACEBOOK_ID_STRING_LIST = "facebook_id_string_list";
	static final String ONLINE_FRIEND_PHONE_NUMBER_LIST = "online_friend_phone_number_list";
	static final String ONLINE_FRIEND_NAME_LIST = "online_friend_name_list";
	static final String ONLINE_FRIEND_AVATAR_LIST = "online_friend_avatar_list";
	static final String ADD_ONLINE_FACEBOOK_FRIEND_RESULT = "add_online_facebook_friend_result";

	static final int LOGIN_ACCOUNT_INTERACT = 102;
	static final int FETCH_ONLINE_FRIEND = 2;
	static final int FETCH_ONLINE_FACEBOOK_FRIEND = 120;
	static final int ACCOUNT_NOT_EXIST = 201;
	static final int WRONG_PASSWORD = 202;
	static final int COMPLETE_LOGIN_ACCOUNT_INTERACT = 203;
	static final int COMPLETE_FETCH_WEB_FACEBOOK_INFO = 1;
	static final int COMPLETE_ADD_ONLINE_FACEBOOK_FRIEND = 2;
	static final int COMPLETE_LOGIN = 3;
	static final int USER_DO_NOT_HAVE_FACEBOOK_FRIEND = 1;
	static final int USER_DO_NOT_HAVE_FACEBOOK_FRIEND_ONLINE = 2;
	static final int ADD_ONLINE_FACEBOOK_FRIEND_OK = 3;
	static final int MENU_CREATE_ACTIVITIY = 1;
	static final int MENU_SHOW_ACTIVITY_DETAIL= 2;
	static final int MENU_SETTINGS = 3;
	static final int COMPLETE_FETCH_ONLINE_FRIEND = 3;
	
	// field
	AppView appView;
	ProgressDialog progressDialog;

	FbMgr fbMgr;
	SharedPreferences preference;
	// TODO	zyc furture remove below
	Bitmap fakeBitmap;
	
	User userOld;
	newTypeUser user;
	

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		
		fbMgr = new FbMgr(this);
		preference = PreferenceManager.getDefaultSharedPreferences(this);

		userOld = new User();
		user = new newTypeUser();
		loadContactsFriend();
		
		fakeBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.cd2)).getBitmap(); 
		loginQuery();
	}
	
	
	public User getUser() {
		return userOld;
	}

	public AppView getAppView() {
		return appView;
	}

	
	void loadContactsFriend() {
		Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
		while (cursor.moveToNext()) {
			long contactId = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID));
			Cursor contacts = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
								  							ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
			long phoneNumber = ToolOld.formatPhoneNumber(contacts.moveToFirst() ? contacts.getString(contacts.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)) : null);
			String contactsName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
			
			Uri contactPhotoUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
			InputStream contactPhotoStream = ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(), contactPhotoUri);
			Bitmap contactsBitmap = (contactPhotoStream == null) ? ((BitmapDrawable) getResources().getDrawable(R.drawable.cd2)).getBitmap() : BitmapFactory.decodeStream(contactPhotoStream);

			user.getFriendNumList().add(phoneNumber);
			
			HashMap<Long, LocalContacts> localContactsMap = new HashMap<Long, LocalContacts>();
			LocalContacts localContacts = new LocalContacts(contactsName, contactsBitmap);
			localContactsMap.put(phoneNumber, localContacts);
		}
	}


	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		menu.add(Menu.NONE, MENU_CREATE_ACTIVITIY, Menu.NONE, "share an activity");
		menu.add(Menu.NONE, MENU_SHOW_ACTIVITY_DETAIL, Menu.NONE, "show activitiy detail");
		menu.add(Menu.NONE, MENU_SETTINGS, Menu.NONE, "settings");
		return true;
	}


	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Intent intent = new Intent();
		
		switch (item.getItemId()) {
		case MENU_CREATE_ACTIVITIY:
			intent.setClass(this, CreateTopicActivity.class);
			intent.putExtra(FRIEND_PHONE_NUMBER, userOld.getPhoneNumber());
			break;
		case MENU_SHOW_ACTIVITY_DETAIL:
			intent.setClass(this, MyTopicDetailActivity.class);
			intent.putExtra(FRIEND_PHONE_NUMBER, userOld.getPhoneNumber());
			break;
		case MENU_SETTINGS:
			intent.setClass(this, SettingsActivity.class);
			break;
		default:
			break;
		}
	
		startActivity(intent);
		return super.onOptionsItemSelected(item);
	}


	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		appView.prepareGridLayoutAxisArray(getResources().getConfiguration().orientation);
	}


	public void loginQuery() {
		final View dialogView = LayoutInflater.from(this).inflate(R.layout.login_query, null);
		(new AlertDialog.Builder(this).setTitle("Login").setView(dialogView)
				.setPositiveButton("OK", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int whichButton) {
						String phoneNumber = ((EditText) dialogView.findViewById(R.id.etLoginPhoneNumber)).getText().toString();
						String password = ((EditText) dialogView.findViewById(R.id.etLoginPassword)).getText().toString();
						if (TextUtils.isEmpty(phoneNumber) || TextUtils.isEmpty(password)) 
							Toast.makeText(MainActivity.this, "empty field is not allowed", Toast.LENGTH_LONG);
						else {
							user.setPhoneNumber(Long.parseLong(phoneNumber));
							user.setPassword(password);
							loginAccountSession();
						}
					}
				}).setNegativeButton("Register", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						startActivityForResult(new Intent(MainActivity.this, RegisterActivity.class), 0);
					}
				})).create().show();
	}
	
	
	public void bindFacebookQuery() {
		if (preference.getBoolean("is_supply_facebook_account", true)) {
			final View dialogView = LayoutInflater.from(this).inflate(R.layout.login_query, null);
			(new AlertDialog.Builder(this).setView(dialogView)
					.setTitle("Bind your FaceBook account?")
					.setPositiveButton("yes", new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int whichButton) {
							// after this call function, if authorize success, MainActivity.fetchWebFacebookInfo() will be called
							fbMgr.authorize();
						}
					}).setNeutralButton("not this time", new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							fetchOnlineFriend();
						}
					}).setNegativeButton("never bind", new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							preference.edit().putBoolean("is_supply_facebook_account", false).commit();
							fetchOnlineFriend();
						}
					})).create().show();
		} else
			fetchOnlineFriend();
	}


	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(requestCode==0)
			if(resultCode==RESULT_OK)
				bindFacebookQuery();
	}


	public void fetchWebFacebookInfo() {
		startProgressBar("", "Loading your facebook information, please wait.");
		new Thread(new Runnable() {
			@Override
			public void run() {
				Message message = new Message();
				
				String responseFriend = fbMgr.request("/me/friends");
				JSONArray jsonArray = null;
				try {
					jsonArray = Util.parseJson(responseFriend).getJSONArray("data");
				} catch (JSONException e) {
					e.printStackTrace();
				} catch (FacebookError e) {
					e.printStackTrace();
				}
				
				ArrayList<String> facebookIdStrList = new ArrayList<String>();
				for (int i = 0; i < jsonArray.length(); i++) {
					try {
						facebookIdStrList.add(jsonArray.getJSONObject(i).getString("id"));
					} catch (JSONException e) {
						e.printStackTrace();
					}
				}
	
				Bundle bundle = new Bundle();
				bundle.putStringArrayList(FACEBOOK_ID_STRING_LIST, facebookIdStrList);
				message.setData(bundle);
	
				String responseMe = fbMgr.request("/me");
				try {
					userOld.setFacebookUserId(Long.parseLong(Util.parseJson(responseMe).getString("id")));
				} catch (NumberFormatException e) {
					e.printStackTrace();
				} catch (JSONException e) {
					e.printStackTrace();
				} catch (FacebookError e) {
					e.printStackTrace();
				}
				
				message.what = COMPLETE_FETCH_WEB_FACEBOOK_INFO;
				mHandler.sendMessageDelayed(message, 0);
			}
		}).start();
	}


	Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message message) {
			switch (message.what) {
			case COMPLETE_LOGIN_ACCOUNT_INTERACT:
				bindFacebookQuery();
				break;
			case COMPLETE_FETCH_WEB_FACEBOOK_INFO:
				addOnlineFacebookFriendToFriendList( message.getData().getStringArrayList(FACEBOOK_ID_STRING_LIST) );
				break;
			case COMPLETE_ADD_ONLINE_FACEBOOK_FRIEND:
				stopProgressBar();
				switch(message.getData().getInt(ADD_ONLINE_FACEBOOK_FRIEND_RESULT)) {
				case USER_DO_NOT_HAVE_FACEBOOK_FRIEND:
					Toast.makeText(MainActivity.this, "You don't have any facebook friend. Please go to facebook site and add one first", Toast.LENGTH_LONG).show();
					break;
				case USER_DO_NOT_HAVE_FACEBOOK_FRIEND_ONLINE:
					Toast.makeText(MainActivity.this, "Now there is no facebook friend login into Share Life", Toast.LENGTH_LONG).show();
					break;
				case ADD_ONLINE_FACEBOOK_FRIEND_OK:
					Toast.makeText(MainActivity.this, "Fetched your facebook friends", Toast.LENGTH_LONG).show();
					break;
				}
				fetchOnlineFriend();
				break;
			case COMPLETE_FETCH_ONLINE_FRIEND:
				Bundle bundle = message.getData();
				
				long[] longArray = bundle.getLongArray(ONLINE_FRIEND_PHONE_NUMBER_LIST);
				ArrayList<Long> friendPhoneNumList = new ArrayList<Long>();
				for(int i=0; i<longArray.length; i++)
					friendPhoneNumList.add(longArray[i]);
				
				ArrayList<String> nameList = bundle.getStringArrayList(ONLINE_FRIEND_NAME_LIST);
				ArrayList<photoByteArray> avatarList = bundle.getParcelableArrayList(ONLINE_FRIEND_AVATAR_LIST);
				
				appView = new AppView(MainActivity.this, user.getPhoneNumber(), friendPhoneNumList, nameList, avatarList);
				setContentView(appView);
				break;
			default:
				break;
			}
		}
	};


	public void addOnlineFacebookFriendToFriendList(final ArrayList<String> facebookIdStrList) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				Socket socket = null;
				DataOutputStream dos = null;
				DataInputStream dis = null;
				try {
					Message message = new Message();
					Bundle bundle = new Bundle();
					
					socket = new Socket(SERVER_IP, 9999);
					dos = new DataOutputStream(socket.getOutputStream());
					dis = new DataInputStream(socket.getInputStream());
					dos.writeInt(FETCH_ONLINE_FACEBOOK_FRIEND);
					if(facebookIdStrList.isEmpty()) {
						dos.writeInt(0);
						bundle.putInt(ADD_ONLINE_FACEBOOK_FRIEND_RESULT, USER_DO_NOT_HAVE_FACEBOOK_FRIEND);
					} else {
						dos.writeInt(facebookIdStrList.size());
						for(String facebookIdStr : facebookIdStrList)
							dos.writeUTF(facebookIdStr);
						int onlineFacebookFriendCount = dis.readInt();
						if(onlineFacebookFriendCount > 0) {
							for(int i=0; i<onlineFacebookFriendCount; i++) {
								User matchedUser = new User();
								matchedUser.receive(dis);
								// TODO zyc must dispose
								Friend friend = new Friend(matchedUser.getPhoneNumber(), "facebook friend", /*matchedUser.fetchBitmap()*/ fakeBitmap);
								userOld.getFriendList().add(friend);
							}
							bundle.putInt(ADD_ONLINE_FACEBOOK_FRIEND_RESULT, ADD_ONLINE_FACEBOOK_FRIEND_OK);
						} else
							bundle.putInt(ADD_ONLINE_FACEBOOK_FRIEND_RESULT, USER_DO_NOT_HAVE_FACEBOOK_FRIEND_ONLINE);
					}
					
					bundle.putStringArrayList(FACEBOOK_ID_STRING_LIST, facebookIdStrList);
					message.setData(bundle);
	
					message.what = COMPLETE_ADD_ONLINE_FACEBOOK_FRIEND;
					mHandler.sendMessageDelayed(message, 0);
				} catch (IOException e) {
					e.printStackTrace();
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					try {
						dis.close();
						dos.close();
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}


	void startProgressBar(String title, String message) {
		if (progressDialog == null)
			progressDialog = ProgressDialog.show(this, title, message);
		progressDialog.show();
	}


	void stopProgressBar() {
		if (progressDialog != null) {
			progressDialog.dismiss();
			progressDialog = null;
		}
	}


	public void fetchOnlineFriend() {
		if(user.getFriendNumList().isEmpty()) {
			Toast.makeText(MainActivity.this, "your don't have any friend, please add some contacts in this phone", Toast.LENGTH_LONG).show();
		}
		new Thread(new Runnable() {
			@Override
			public void run() {
				Socket socket = null;
				DataOutputStream dos = null;
				DataInputStream dis = null;
				try {
					socket = new Socket(SERVER_IP, 9999);
					dos = new DataOutputStream(socket.getOutputStream());
					dis = new DataInputStream(socket.getInputStream());
					dos.writeInt(FETCH_ONLINE_FRIEND);
					
					ArrayList<Long> onlineFriendPhoneNumList = new ArrayList<Long>();
					ArrayList<String> nameList = new ArrayList<String>();
					ArrayList<photoByteArray> avatarList = new ArrayList<photoByteArray>();
					
					ArrayList<Long> friendNumList = user.getFriendNumList();
					dos.writeInt(friendNumList.size());
					for(Long friendPhoneNum : friendNumList) {
						dos.writeLong(friendPhoneNum);
						if(dis.readBoolean()) {
							onlineFriendPhoneNumList.add(dis.readLong());
							nameList.add(dis.readUTF());
							avatarList.add(new photoByteArray(Tool.receiveByteArray(dis)));
						}
					}
					
					Message message = new Message();
					Bundle bundle = new Bundle();
					
					int size = onlineFriendPhoneNumList.size();
					long[] longArray = new long[size];
					Long[] tempLongArray = (Long[])onlineFriendPhoneNumList.toArray(new Long[size]);
					for(int i=0; i<size; i++)
						longArray[i] = tempLongArray[i].longValue();
					bundle.putLongArray(ONLINE_FRIEND_PHONE_NUMBER_LIST, longArray);
					bundle.putStringArrayList(ONLINE_FRIEND_NAME_LIST, nameList);
					bundle.putParcelableArrayList(ONLINE_FRIEND_AVATAR_LIST, avatarList);
					
					message.setData(bundle);
					message.what = COMPLETE_FETCH_ONLINE_FRIEND;
					mHandler.sendMessageDelayed(message, 0);
				} catch (IOException e) {
					e.printStackTrace();
				} catch (InterruptedException e) {
					e.printStackTrace();
				} finally {
					try {
						dis.close();
						dos.close();
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
	
	
	void loginAccountSession() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				Socket socket = null;
				DataOutputStream dos = null;
				DataInputStream dis = null;
				try {
					socket = new Socket(SERVER_IP, 9999);
					dos = new DataOutputStream(socket.getOutputStream());
					dis = new DataInputStream(socket.getInputStream());
					dos.writeInt(LOGIN_ACCOUNT_INTERACT);
					dos.writeLong(user.getPhoneNumber());
					if(dis.readBoolean()) {
						dos.writeUTF(user.getPassword());
						if(dis.readBoolean()) {
							user.setName(dis.readUTF());
							user.setAvatar(Tool.receiveByteArray(dis));
							mHandler.sendEmptyMessageDelayed(COMPLETE_LOGIN_ACCOUNT_INTERACT, 0);
						} else
							mHandler.sendEmptyMessageDelayed(WRONG_PASSWORD, 0);
					} else
						mHandler.sendEmptyMessageDelayed(ACCOUNT_NOT_EXIST, 0);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					try {
						dis.close();
						dos.close();
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();
	}
}
